# -*- coding: utf-8 -*-

###############################################################################
# Copyright [2010] [Roberto Carrasco - rcarrasco@talentus.cl]
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License. 
###############################################################################

"""Process NMEA response"""

from operator import xor

class NmeaResponse:
    def __init__(self, _message):
        self.message = _message
        self.valid = False
        self.crc_ok = self.crc_check(self.message)
        if self.crc_ok:
            self.valid = True
            c = self.message[-5]
            self.message[-5] = ord(',')
            message = str(self.message[0:-2 ]).split(',')
            self.message[-5] = c
            self.messageId = message[0]
            if self.messageId == '$GPGGA':
                self.utcTime = message[1]
                self.latitude = message[2] + ' ' + message[3]
                self.longitude = message[4] + ' ' + message[5]
                self.positionFix = message[6]
                self.satellitesUsed = message[7]
                self.hdop = message[8]
                self.mslAltitude = message[9] + ' ' + message[10]
                self.geoidSeparation = message[11] + ' ' + message[12]
                self.ageOfDifferentialCorrections = message[13]
                self.diffReferenceCorrections = message[14]
            elif self.messageId == '$GPGLL':
                self.latitude = message[1] + ' ' + message[2]
                self.longitude = message[3] + ' ' + message[4]
                self.utcTime = message[5]
                self.status = message[6]
                self.modeIndicator = message[7]
            elif self.messageId == '$GPGSA':
                self.mode = message[1]
                self.fix = message[2]
                self.svOnChannel = message[3:15]
                self.pdop = message[15]
                self.hdop = message[16]
                self.vdop = message[17]
            elif self.messageId == '$GPGSV':
                self.numberOfMessages = int(message[1])
                self.messageNumber = int(message[2])
                self.satellitesInView = int(message[3])
                self.satellites = []
                for i in range(0, 4):
                    s = type('ANONYMOUS', (object,), dict())
                    s.satelliteId = ''
                    s.elevation = ''
                    s.azimuth = ''
                    s.snr = ''
                    self.satellites.append(s)
                    idx = 4 + i * 4
                    if idx < len(message) - 1:
                        s.satelliteId = message[idx + 0]
                        s.elevation = message[idx + 1]
                        s.azimuth = message[idx + 2]
                        s.snr = message[idx + 3]
            elif self.messageId == '$GPRMC':
                self.utcTime = message[1]
                self.status = message[2]
                self.latitude = message[3] + ' ' + message[4]
                self.longitude = message[5] + ' ' + message[6]
                self.speedOverGround = message[7]
                self.courseOverGround = message[8]
                self.date = message[9]
                self.magneticVariation = message[ 10 ] + ' ' + message[ 11 ]
                self.mode = message[12]
            elif self.messageId == '$GPVTG':
                self.courseTrue = message[1]
                self.referenceTrue = message[2]
                self.courseMagnetic = message[3]
                self.referenceMagnetic = message[4]
                self.speedInKnots = message[5]
                self.unitsKnots = message[6]
                self.speedInKmh = message[7]
                self.unitsKmh = message[8]
                self.mode = message[9]
            else:
                self.valid = False

    def crc_check(self, bytes):
        # $GPXXX,....,....*XX 0x0d 0x0a
        size=len(bytes)
        crc_received = int(str(bytes[ size-4:size-2]), 16)
        crc_calculated = reduce(xor, bytes[1:size-5])
        return crc_calculated == crc_received
